iT邦幫忙

2024 iThome 鐵人賽

DAY 30
0
DevOps

《30天挑戰精通 PowerShell:從 Windows Server 到 Azure DevOps 自動化之旅》系列 第 30

Day 30 - 將 CI/CD 流程透過 Azure DevOps 去執行吧 - 完結。

  • 分享至 

  • xImage
  •  

今天我們將延續前幾天的案例分享,完成整個 CD(持續部署)流程,並把範例前端部署到 Windows Server 的 IIS 上。這代表著,我們正式完成了將 CI/CD 流程透過 Azure DevOps 的目標。


在 Azure DevOps 建立 Release

建立空白 Pipeline

1. 進入 Azure DevOps Release 頁面

在左側導航欄點擊 「 Release 」 以進入 Release 管理頁面。
https://ithelp.ithome.com.tw/upload/images/20241014/20168708L6H1vr4pGN.png

2. 點擊 New Pipeline

點擊頁面中央的藍色按鈕 「 New Pipeline 」,開始建立新的 pipeline。
https://ithelp.ithome.com.tw/upload/images/20241014/20168708Paf7JGEw5l.png

3. 選擇 Empty job

這裡我們選擇 「 Empty job 」,不使用任何模板,直接從空白開始建立。
https://ithelp.ithome.com.tw/upload/images/20241014/20168708mb4vimK4pH.png

設定 Source

1. 點擊 Add an artifact

點擊頁面上的 「 Add an artifact 」,選擇 artifact 來源。
https://ithelp.ithome.com.tw/upload/images/20241014/20168708meOzYB39ok.png

2. 選擇 Source Type 及 Source

Azure Pipelines 支援各種儲存庫、服務和 CI/CD 平台。建立版本時,您可以指定工件來源的版本。預設情況下,版本使用來源工件的最新版本。您也可以透過指定標籤、特定版本來選擇使用特定分支的最新版本,或允許使用者在建立版本時指定版本。
Reference - Artifact sources in Classic release pipelines
https://ithelp.ithome.com.tw/upload/images/20241014/20168708w3MGsMaiwk.png

選擇好 Source 後,Azure DevOps 會自動抓取最新的版本,點擊 「 Add 」完成工件的新增。
https://ithelp.ithome.com.tw/upload/images/20241014/20168708ttQMX8Dbek.png

設定自動部署

1. 設定自動觸發器

點擊剛新增的工件右上角的閃電符號以進入觸發設定。
https://ithelp.ithome.com.tw/upload/images/20241014/201687085fMwYsW2Gk.png

2. 啟用自動觸發

啟用自動觸發後,每當有新版本可用時都會自動建立 Release。
https://ithelp.ithome.com.tw/upload/images/20241014/20168708NkuBUNUWd4.png

啟用成功後,閃電符號上會顯示勾選符號,表示自動觸發器已設置成功。
https://ithelp.ithome.com.tw/upload/images/20241014/20168708B0SuMbmxx6.png


Stage 設定

Pre-deployment conditions

此選項有兩個常見的功能:

  • 可以為不同的 Stage 設定觸發方式,例如自動部署(after release)、僅手動部署(Manual only)或是在某個 Stage 完成後觸發。
  • 可以在 Stage 運行前要求批准,透過 Pre-deployment approvals 指定負責審核部署的人員。

1. 點擊 Stage 1 該項選單

點擊 Stage 1 方框左側的紅框以開啟該選單
https://ithelp.ithome.com.tw/upload/images/20241014/20168708aGQnn3qujE.png

2. 確認該 Stage 將自動部署

確認該 Stage 被設置為自動部署,確保部署流程順暢。
https://ithelp.ithome.com.tw/upload/images/20241014/20168708GcjzlF4L3F.png

設定 Stage

1. 點選 Stage 的簡略連結

如下圖紅框所示,目前該 Stage 有一個 Job 及 0 個 task,我們可以透過點擊,進入細節設定。
https://ithelp.ithome.com.tw/upload/images/20241014/20168708K5mE3evMde.png

2. 修改 Stage 名稱

在設定頁面將 Stage 名稱更改為 "Azure Server 1" 以便識別。
https://ithelp.ithome.com.tw/upload/images/20241014/201687081HWsTkS75B.png

3. Stage 裡三種 Job 的類型

點擊三連點可以看到,有三種不同類型的 job 可以選擇:Agent job、Deployment group job 和 Agentless job,預設會是透過 Azure Agent 所執行的 Job ( Add an agent job )。
https://ithelp.ithome.com.tw/upload/images/20241014/20168708Utw2BCij9y.png

  • Agent Job:在代理程式上執行需要計算資源的工作,例如編譯、測試和部署。
  • Deployment Group Job:針對多台伺服器執行部署,適合部署到自有基礎設施中的多個目標。
  • Agentless Job:不需要代理程式,執行輕量任務,如調用 API 或發送通知。

設定 Job

Job 是任務的邏輯分組,定義執行任務的運行環境。以下是一些關鍵設定:

1. 修改 Job 名稱

將 Job 名稱更改為 "deploy",使其更具描述性。
https://ithelp.ithome.com.tw/upload/images/20241014/20168708B1Pv78RAY2.png

2. 選擇自託管 agent

在 Agent Pool 中選擇 "30dayPool" 作為運行的 Agent Pool。
https://ithelp.ithome.com.tw/upload/images/20241014/20168708T7tkOwNLCm.png

3. 進階功能的補充資訊 - Demands

透過 Demands 的設定,我們可以為每個不同的 Job 透過 Filter 的方式使特定的 Job 僅供 Agent Pool 內特定的 Agent 運行,其 filter 的方式請參考這篇連結。
https://ithelp.ithome.com.tw/upload/images/20241014/20168708FeFioPE0Xx.png

4. 進階功能的補充資訊 - Execution Plan

Execution Plan 部分可以為代理程式設定在執行任務時的相關策略和參數:
https://ithelp.ithome.com.tw/upload/images/20241014/20168708IRnyhtvjdX.png

  • Parallelism(平行性)允許你選擇作業的並行執行方式。預設選項為 None,表示任務不會並行執行,所有的步驟都會順序完成,選擇 Multi-configuration 則可允許該作業在多個配置(例如不同的環境參數或不同的系統)下進行並行執行(適合進行跨平台測試或多變數部署),若選擇 Multi-agent 則是允許使用多個代理程式來並行處理相同的工作,這對於提升大型部署任務的速度和效率非常有幫助。
  • Timeout(逾時)可指定作業在代理程式上執行的最大時間(以分鐘為單位)。如果作業執行時間超過這個設定值,則作業會被強制取消,這可以用來防止無限等待的情況發生,例如當某些步驟因為某些未知原因無法結束時,通過設置超時可以避免浪費代理程式的資源。
  • Job Cancel Timeout(作業取消逾時)讓我們在取消作業時,給每個步驟結束的時間(以分鐘為單位)。如果步驟在此設定的時間內無法正常結束,它將被強制終止,這個選項的目的是確保在用戶手動取消或者系統決定終止該作業時,可以更好地控制每個步驟的結束過程,不至於長時間掛起在某個步驟。

5. 進階功能的補充資訊 - Additional Options

Additional Options 部分提供了一些額外的選項,用於更靈活地控制作業的執行行為及其條件:
https://ithelp.ithome.com.tw/upload/images/20241014/20168708pwN7Ixwi5N.png

  • Skip download of artifacts(跳過下載工件),勾選這個選項將讓代理程式在執行此作業時跳過工件(如編譯產物、測試結果等)的下載步驟,該選項適合在不需要依賴任何之前生成的 artifact 的情況下使用,這樣可以減少下載 artifact 所需的時間,進一步提升作業效率。
  • Allow scripts to access the OAuth token(允許腳本存取 OAuth Token ),勾選這個選項可以讓作業中的腳本存取 OAuth Token,用於與 Azure DevOps 進行認證和互動。這非常有用,特別是在腳本中需要進行 API 調用或對系統進行安全操作時,它可以讓腳本順利完成對 Azure DevOps 的授權操作。
  • Run this job(執行此作業):這部分允許你設定作業的執行條件。預設的選項是 Only when all previous jobs have succeeded(僅當所有之前的作業成功時執行)。這樣的設定確保只有當之前所有的作業都完成且成功時,當前作業才會開始執行,以避免失敗的作業進一步導致錯誤或浪費資源。

建立 Service connections

Service connections 是 Azure Pipelines 與用於執行作業中的任務的外部或遠端服務之間經過驗證的連線。部分 Pipeline 所使用的 task 可使用該認證方法,因此先建立起來,稍後會使用到。

點選 Project settings 裡的 Service connections。
https://ithelp.ithome.com.tw/upload/images/20241014/20168708O2ubp1Ut8a.png

點擊右上角的 New service connection 按鍵。
https://ithelp.ithome.com.tw/upload/images/20241014/2016870819TRJtXYRH.png

建立 SSH 使用的 connection。
https://ithelp.ithome.com.tw/upload/images/20241014/20168708JOEHfrJbTd.png

填入必要資訊。
https://ithelp.ithome.com.tw/upload/images/20241014/20168708GVf1rE6p6V.png

完成後,會顯示在頁面上。
https://ithelp.ithome.com.tw/upload/images/20241014/201687082Z7cQy4f1g.png


在 Agent Job 建立個別的 Task

這邊紀錄幾個對我來說比較棘手的點:

1. 將 artifact 下載到目前 pipeline 目錄( agent )

還記得昨天 CI 過程中我們為 artifact name 的命名規則,將其補上其規則。

steps:
- task: DownloadPipelineArtifact@2
  displayName: 'Download Pipeline Artifact'
  inputs:
    artifactName: 'quasar-dist-$(Build.BuildNumber)'

2. 透過 Linux Agent 使用 SSH Copy file 到 Windows 時

CopyFilesOverSSH 這個 Task 會預設使用你所建立的 service connection 裡的連線帳號的家目錄底下。
有嘗試透過這篇 What is the home directory on Windows Subsystem for Linux? 去切換到 D 槽,但是我測試到目前只能使用到 C:\,供參考。
另外:其中的 sshEndpoint 就是透過 service connection 所提供。

steps:
- task: CopyFilesOverSSH@0
  displayName: 'Securely copy files to the remote machine'
  inputs:
    sshEndpoint: 'server-a'
    sourceFolder: '$(Pipeline.Workspace)/spa'
    targetFolder: /app
    isWindowsOnTarget: true
  enabled: true

上面的 script 最終會 download 在 pipeline folder 裡的 artifact 前端靜態資源 copy 到目標 server 的 C:\app 底下。

3. 透過 Linux Agent 使用 SSH 連線到 Windows Server 執行 ps1 script 時

powershell -ExecutionPolicy Bypass -File C:\Tools\deployAppPool.ps1
powershell -ExecutionPolicy Bypass -File C:\Tools\deployAppSite.ps1

可另外搭配 Pipeline variables 做使用,透過 scope 的設定,讓不同的 stage 能帶進不同的參數,這個使用方法,之後有機會再另外寫一篇出來講。

4. 主要使用的 powershell script

硬編碼範例

  • 建立 application pool。
# 导入 WebAdministration 模块
Import-Module WebAdministration

# 定义应用程序池名称
$AppPoolName = "MyAppPool"

# 检查应用程序池是否存在,如果不存在则创建
if (-not (Get-Item IIS:\AppPools\$AppPoolName -ErrorAction SilentlyContinue)) {
    # 创建新的应用程序池
    New-Item IIS:\AppPools\$AppPoolName

    # 设置应用程序池的属性
    Set-ItemProperty IIS:\AppPools\$AppPoolName -Name "managedRuntimeVersion" -Value "v4.0"
    Set-ItemProperty IIS:\AppPools\$AppPoolName -Name "processModel.identityType" -Value "ApplicationPoolIdentity"

    Write-Host "应用程序池 '$AppPoolName' 已创建。"
} else {
    Write-Host "应用程序池 '$AppPoolName' 已存在。"
}
  • 建立 website。
# 导入 WebAdministration 模块
Import-Module WebAdministration

# 定义变量
$SiteName = "MyWebsite"
$AppPoolName = "MyAppPool"
$PhysicalPath = "C:\inetpub\wwwroot\MyWebsite"
$BindingProtocol = "http"
$Port = 8888
$IPAddress = "*"
$HostHeader = ""

# 检查物理路径是否存在,不存在则创建
if (-not (Test-Path $PhysicalPath)) {
    New-Item -Path $PhysicalPath -ItemType Directory -Force
}

# 检查网站是否存在,如果不存在则创建
if (-not (Get-Item IIS:\Sites\$SiteName -ErrorAction SilentlyContinue)) {
    # 创建新的网站
    New-Item IIS:\Sites\$SiteName -PhysicalPath $PhysicalPath -Bindings @{protocol=$BindingProtocol; bindingInformation="$IPAddress`:$Port`:$HostHeader"} -ApplicationPool $AppPoolName

    Write-Host "网站 '$SiteName' 已创建并绑定到端口 $Port。"
} else {
    Write-Host "网站 '$SiteName' 已存在。"
}

動態調整

  • 將建立 website 的 script 使用 param 的方式讓 script 動態調整參數 value。
# 导入 WebAdministration 模块
Import-Module WebAdministration

Param(
    [string]$SiteName = "MyWebsite",
    [string]$AppPoolName = "MyAppPool",
    [string]$PhysicalPath = "C:\inetpub\wwwroot\MyWebsite",
    [string]$BindingProtocol = "http",
    [int]$Port = 8888,
    [string]$IPAddress = "*",
    [string]$HostHeader = ""
)

# 检查物理路径是否存在,不存在则创建
if (-not (Test-Path $PhysicalPath)) {
    New-Item -Path $PhysicalPath -ItemType Directory -Force
}

# 检查网站是否存在,如果不存在则创建
if (-not (Get-Item IIS:\Sites\$SiteName -ErrorAction SilentlyContinue)) {
    # 创建新的网站
    New-Item IIS:\Sites\$SiteName -PhysicalPath $PhysicalPath -Bindings @{protocol=$BindingProtocol; bindingInformation="$IPAddress`:$Port`:$HostHeader"} -ApplicationPool $AppPoolName

    Write-Host "网站 '$SiteName' 已创建并绑定到端口 $Port。"
} else {
    Write-Host "网站 '$SiteName' 已存在。"
}
  • 對應在運行 ssh 的 command 裡加入參數及參數值。
powershell -ExecutionPolicy Bypass -File 'C:\Tools\deployAppSite.ps1' `
  -SiteName '$(SiteName)' `
  -AppPoolName '$(AppPoolName)' `
  -PhysicalPath '$(PhysicalPath)' `
  -BindingProtocol '$(BindingProtocol)' `
  -Port $(Port) `
  -IPAddress '$(IPAddress)' `
  -HostHeader '$(HostHeader)'

手動運行 Release

可以透過 Release 的頁面,新增 release。
https://ithelp.ithome.com.tw/upload/images/20241014/20168708JGsExhXaY0.png

可以選取你想要的 version,並且依據當次任務需求決定是否有需要 trigger step。
https://ithelp.ithome.com.tw/upload/images/20241014/20168708ZXqYytMrxU.png


尚未寫完的章節

  • Pipeline variables & Variable groups。
  • Scope。
  • 好用的 Test groups。
  • Azure Artifact。
  • Test Plans。

結語

連續分享技術文章 30 天不間斷的挑戰就要在今天結束了,開心之餘除了將陸續將上述未完成的章節研究完,也期許自己能夠在接下來的日子裡,產出一些有參考價值的文章,以時時充滿好奇心的心態,去探索一切,下次見。


上一篇
Day 29 - 將 CI/CD 流程透過 Azure DevOps 去執行吧 - Part 3
系列文
《30天挑戰精通 PowerShell:從 Windows Server 到 Azure DevOps 自動化之旅》30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言